﻿//*** Guidance generated code ***//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Web.Configuration;

using Survey.Common.Business.Services;
using Survey.Entity.Services;

using ProjectBase.Core;
using ProjectBase.Core.Service;
using ProjectBase.Mvc;

namespace Survey.Common.Providers
{
    /// <summary>
    ///     Provides the ASP.NET 'resource' functionality based on ResourceManager
    /// </summary>
    public class ResourceFinder
    {
        #region members
        const string DefaultArea = "";
        string _defaultLang;
        GlobalizationSection _globalization;
        ITranslatorFacade _translatorFacade;
        #endregion members

        #region GetResource

        /// <summary>
        ///     provides the localization of the passed 'key' phrase
        /// </summary>
        /// <param name = "culture">culture (language) to be used for localization</param>
        /// <param name = "key">The unique key for a phrase</param>
        /// <param name = "area">more precise key setting (can be nullOrEmpty)</param>
        /// <returns>Translated phrase</returns>
        public virtual string GetResourceByCultureAndKey(CultureInfo culture, string key, string area)
        {
            if (key.IsEmpty())
            {
                return string.Empty;
            }
            area = area ?? string.Empty;
            var ci = culture ?? new CultureInfo(DefaultLanguage);
            var defaultLang = DefaultLanguage;

            // Find Translator object
            var t = Find(key, area);
            if (t.Is())
            {
                // I. Exact match for CultureName
                if (t.Translations.ContainsKey(ci.Name)
                    && t.Translations[ci.Name].IsNotEmpty())
                {
                    return t.Translations[ci.Name];
                }

                // II. try to find out language without culture
                if (ci.Name != ci.TwoLetterISOLanguageName
                    && t.Translations.ContainsKey(ci.TwoLetterISOLanguageName)
                    && t.Translations[ci.TwoLetterISOLanguageName].IsNotEmpty())
                {
                    return t.Translations[ci.TwoLetterISOLanguageName];
                }

                // III. still not found , let's try search without area
                if (area.IsNotEmpty())
                {
                    var text = GetResourceByCultureAndKey(CultureInfo.CurrentUICulture, key, string.Empty);
                    if (!text.EndsWith(key, StringComparison.Ordinal))
                    {
                        return text;
                    }
                }

                // IV. the last test could be searched for default language
                if (t.Translations.ContainsKey(defaultLang)
                    && t.Translations[defaultLang].IsNotEmpty())
                {
                    return t.Translations[defaultLang];
                }
            }
            return Prefix + key;
        }

        /// <summary>
        ///     Firstly finds the translator object with key and area,
        ///     if not found, then only key is used for searching
        /// </summary>
        /// <param name = "key">The unique key for a phrase</param>
        /// <param name = "area">more precious key setting (can be nullOrEmpty)</param>
        /// <returns>Translator object with available translated phrases</returns>
        protected virtual Translator Find(string key, string area)
        {
            return Translations.IsEmpty()
                ? null
                : Translations
                .Where(t => t.Key.Equals(key) && (t.Area.Equals(area) || t.Area.IsEmpty()))
                .OrderBy(t => t.Area.IsNotEmpty() ? 0 : 1)
                .FirstOrDefault();
        }
        #endregion GetResource

        #region GetDictionary
        /// <summary>
        ///     Serves for IResourceReader as the IDictionary provider.
        ///     Be carefull about using it. Only resources known in compile time are changeable
        /// </summary>
        /// <param name = "culture"></param>
        /// <param name = "area"></param>
        /// <returns></returns>
        public virtual IDictionary GetDictionaryByCultureAndArea(CultureInfo culture, string area)
        {
            var result = Translations
                .Where(t => t.Area.IsEqual(area));
            var common = Translations
                .Where(t => t.Area.IsEqual(string.Empty)
                            && !result.Any(r => r.Key.Equals(t.Key)));
            return result.Union(common)
                .ToDictionary(t => t.Key, t => GetValue(t.Translations, culture));
        }

        protected virtual string GetValue(IDictionary<string, string> translations, CultureInfo culture)
        {
            if (translations.ContainsKey(culture.Name))
            {
                return translations[culture.Name];
            }
            if (translations.ContainsKey(culture.TwoLetterISOLanguageName))
            {
                return translations[culture.TwoLetterISOLanguageName];
            }
            return translations.ContainsKey(DefaultLanguage)
                       ? translations[DefaultLanguage]
                       : string.Empty;
        }
        #endregion GetDictionary

        #region properties
        protected virtual GlobalizationSection Globalization
        {
            get { return _globalization ?? (_globalization = ConfigurationManager.GetSection("system.web/globalization") as GlobalizationSection); }
            set { _globalization = value; }
        }
        protected virtual ITranslatorFacade TranslatorFacade
        {
            get { return _translatorFacade ?? (_translatorFacade = Factory.CreateInstance<ITranslatorFacade>()); }
        }
        protected virtual IEnumerable<Translator> Translations
        {
            get { return TranslatorFacade.GetAll(); }
        }
        protected virtual string Prefix
        {
            get { return Global.Settings.PrefixForNotFoundTranslation; }
        }

        /// <summary>
        ///     Gets the settings from web.config/globlization/UIculture/auto:?
        /// </summary>
        /// <returns>Default or English (en) if no default is set in web.config</returns>
        protected virtual string DefaultLanguage
        {
            get
            {
                if (_defaultLang.IsEmpty())
                {
                    var lang = "en";
                    var arr = Globalization.UICulture.Split(':');
                    if (arr.Length > 1
                        && arr[1].Length > 1)
                    {
                        lang = arr[1].Split('-')[0];
                    }
                    _defaultLang = lang;
                }
                return _defaultLang;
            }
        }
        #endregion private
    }
}